package com.jiufengxinxi.ts.device.interfaces;


import com.jiufengxinxi.ts.common.utils.HexUtil;
import com.jiufengxinxi.ts.device.callback.IDeviceStateCallback;
import com.jiufengxinxi.ts.device.callback.IODeviceCallback;
import gnu.io.SerialPortEvent;

import java.io.InputStream;
import java.util.Date;
import java.util.regex.Pattern;

public class IOCommDevice extends ICommDevice {
	
	private String addr;
	
	//private int[] sites;

	private Thread ioThread=null;
	
	
	private boolean weriting=false;
	
	/**
	 * 是否处理IO信息
	 */
	private boolean proIoMessage=true;
	
	private boolean started = false;

	private int sleepTime=300;

	private long lastCallbackTimes = 0;

	private Pattern pattern = Pattern.compile("^[\\>]{0,1}[0-9A-za-z]{4,}");
	
	public IOCommDevice(String port, String addr, IODeviceCallback deviceCallback) {
		super(port,deviceCallback);
		this.addr=addr;
		/*String[] temps=site.split(",");
		sites=new int[temps.length];
		for(int i=0;i<temps.length;i++){
			sites[i]=Integer.parseInt(temps[i]);
		}*/


		new Thread(new Runnable() {
			@Override
			public void run() {
				while (true){
					try{
						if(ioThread!=null&&lastCallbackTimes!=0&&new Date().getTime()-lastCallbackTimes>sleepTime*50) {
							destroy();
							try {
								Thread.sleep(2000);
							} catch (InterruptedException e) {
							}
							startup();
						}
						try {
							Thread.sleep(1000);
						} catch (InterruptedException e) {
						}
					}catch (Exception e){}
				}
			}
		}).start();

		startIOStream();

	}

	@Override
	public void produceSinal(String sinal) {
		try{
			// m System.out.print(sinal+"/");

			lastCallbackTimes = new Date().getTime();

			if(proIoMessage) {
				if(!pattern.matcher(sinal).find()) {
					return;
				}
				
				if(sinal.startsWith(">")) {
					sinal=sinal.substring(3, 5);
				}else {
					sinal=sinal.substring(2, 4);
				}
				
				//System.out.println("ori_ "+sinal);
				
				String regex="^[0-9a-fA-F]+$";
				if(!sinal.matches(regex)){
					return;
				}
				sinal=new StringBuffer(HexUtil.hexString2binaryString(sinal)).reverse().toString();
			}
			getDeviceCallback().callBack(getGateNo(),sinal);
		}catch (Exception e) {
			e.printStackTrace();
		}
		
	}

	@Override
	public void produceSinal(byte[] sinal) {
		lastCallbackTimes = new Date().getTime();
	}

	@Override
	public void destroy() {
		if(ioThread!=null){
			ioThread.interrupt();
		}
		started = false;
		close();
	}
	
	@Override
	public String getDeviceName() {
		return "IO";
	}
	
	@Override
	public void startup(){
		super.startup();
		//startIOStream();
		started = true;
		lastCallbackTimes = new Date().getTime();
	}
	
	public void startIOStream(){
		if(ioThread==null){
			ioThread=new Thread(new Runnable() {
				
				@Override
				public void run() {
					while(true){

						try {
							if (started&&!weriting) {
								write("@" + addr + "\r");
							}
							//System.out.println("tigger order"+getGateNo()+"@"+addr+"\r");
							try {
								Thread.sleep(sleepTime);
							} catch (InterruptedException e) {
								//e.printStackTrace();
							}
						}catch (Exception e){
							//log();
							e.printStackTrace();
						}
					}
				}
			});
		}
		if(!ioThread.isAlive()){
			ioThread.start();
		}
	}
	
	public void writeCommand(String channel,String order){
		writeCommand(channel,order,3);
	}
	
	public void writeCommand(String channel,String order,int count){
		try{
			synchronized (channel) {

				weriting = true;
				for (int i = 0; i < count; i++) {
					write("#" + addr + "A" + channel + order + "\r");
					try {
						Thread.sleep(50);
					} catch (InterruptedException e) {
						//e.printStackTrace();
					}
				}
				Thread.sleep(100);
			}
		}catch (Exception e) {
			e.printStackTrace();
			//logger.error();
		}finally {
			weriting=false;
		}
		
	}
	
	
	/**
     * 数据接收的监听处理函数
     */
    @Override
    public void serialEvent(SerialPortEvent arg0) {
        switch(arg0.getEventType()){
	          case SerialPortEvent.BI:/*Break interrupt,通讯中断*/  break;
	          case SerialPortEvent.OE:/*Overrun error，溢位错误*/ break;
	          case SerialPortEvent.FE:/*Framing error，传帧错误*/ break;
	          case SerialPortEvent.PE:/*Parity error，校验错误*/ break;
	          case SerialPortEvent.CD:/*Carrier detect，载波检测*/	 break;
	          case SerialPortEvent.CTS:/*Clear to send，清除发送*/  break;
	          case SerialPortEvent.DSR:/*Data set ready，数据设备就绪*/ break;
	          case SerialPortEvent.RI:/*Ring indicator，响铃指示*/break;
	          case SerialPortEvent.OUTPUT_BUFFER_EMPTY:/*Output buffer is empty，输出缓冲区清空*/ 
	              break;
	          case SerialPortEvent.DATA_AVAILABLE:/*Data available at the serial port，端口有可用数据。读到缓冲数组，输出到终端*/
	        	  //connect=true; msg="连接正常";
	              InputStream inputStream=getInputStream();

				  lastCallbackTimes = new Date().getTime();
	              
	              byte[] readBuffer = new byte[4];
	              String readStr="";
	              //String s2 = "";
	              try {
	                  
	                  while (inputStream.available() > 0) {
	                      inputStream.read(readBuffer);
	                      readStr += new String(readBuffer).trim();
	                  }
	                	  
                	  log("接收到端口返回数据(长度为"+readStr.length()+")："+readStr);
	                  
	              } catch (Exception e) {
	              	e.printStackTrace();
	            	  close();
	              }
	              produceSinal(readStr);
        }
    }

	public String getAddr() {
		return addr;
	}

	public void setAddr(String addr) {
		this.addr = addr;
	}

	public Thread getIoThread() {
		return ioThread;
	}

	public void setIoThread(Thread ioThread) {
		this.ioThread = ioThread;
	}

	public boolean isWeriting() {
		return weriting;
	}

	public void setWeriting(boolean weriting) {
		this.weriting = weriting;
	}

	public boolean isProIoMessage() {
		return proIoMessage;
	}

	public void setProIoMessage(boolean proIoMessage) {
		this.proIoMessage = proIoMessage;
	}

	public int getSleepTime() {
		return sleepTime;
	}

	public void setSleepTime(int sleepTime) {
		this.sleepTime = sleepTime;
	}

	@Override
	public void setDeviceCallback(IDeviceStateCallback deviceCallback) {
		// TODO Auto-generated method stub
		
	}
	
	
	/*@Override
	public void startRead() {
		super.startRead();
		while(true){
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			//byte[] cs=new byte[];
			byte[] a = new byte[4];
	        int len = 0;
	        try {
				while((len = getInputStream().read(a))>0){
				    bos.write(a,0,len);
				    len=0;
				}
				//bos.write(a,0,len);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	        
	        String str = bos.size()>0?bos.toString():"";
	        System.out.println(str);
		}
	}*/

//	public static void main(String[] args) {
//		IOCommDevice comm=new IOCommDevice("COM17","01",new TriggerDeviceCallback("0,1"));
//		comm.init("6");
//		//comm.writeCommand("1", "01");
//	}

}
